package com.yx.changdao.common.utils;

import com.yx.changdao.common.exception.AlertException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description: <br/>
 * 上传文件
 * <p>
 * <br/>
 * @Auther: zhangqi
 * @create 2019/11/19 9:31
 */
@Component
public class UploadUtils {

    /**
     * 允许上传图片的类型
     */
    private static List<String> contentTypes;

    /**
     * 允许上传文件的大小 单位: B
     */
    private static Long fileSize;

    /**
     * 允许上传图片的大小 单位: B
     */
    private static Long imageSize;

    /**
     * 文件保存到服务器的路径
     */
    private static String saveFileServerPath;

    /**
     * 图片保存到服务器的路径
     */
    private static String saveImageServerPath;

    /**
     * 访问图片的http地址 注: 需要修改Nginx配置
     */
    private static String imageHttpUrl;

    /**
     * 文件图片的http地址 注: 需要修改Nginx配置
     */
    private static String fileHttpFile;

    // 日志
    private static Logger LOGGER = LoggerFactory.getLogger(UploadUtils.class);

    /**
     * 批量上传
     *
     * @param files
     * @return
     * @throws AlertException
     */
    public static List<String> batchUploadImage(List<MultipartFile> files) throws AlertException {
        List<String> urls = new ArrayList<>();

        files.forEach(t -> {
            try {
                urls.add(uploadImage(t));
            } catch (AlertException e) {
                urls.add(t.getOriginalFilename() + " 上传失败!");
            }
        });

        return urls;
    }

    /**
     * 上传图片
     *
     * @param file
     * @return
     */
    public static String uploadImage(MultipartFile file) throws AlertException {
        // 获取当前时间
        String filePath = new SimpleDateFormat("YYYY/MM/dd/").format(new Date());

        String originalFilename = file.getOriginalFilename();
        // 校验文件的类型
        String contentType = file.getContentType();
        if (!contentTypes.contains(contentType)) {
            // 文件类型不合法，直接返回null
            LOGGER.info("文件类型不合法：{}", originalFilename);
            throw new AlertException("文件类型不合法：" + originalFilename);
        }

        // 判断文件大小
        if (file.getSize() > imageSize) {
            LOGGER.info("上传图片超过最大限制：" + originalFilename);
            throw new AlertException("上传图片超过最大限制：" + originalFilename);
        }

        try {
            // 校验文件的内容
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            if (bufferedImage == null) {
                LOGGER.info("文件内容不合法：{}", originalFilename);
                throw new AlertException("文件内容不合法：" + originalFilename);
            }

            // 完整的保存服务器地址
            String newFilePath = saveImageServerPath + filePath;

            // 判断文件夹是否存在
            if (!new File(newFilePath).exists()) {
                // 不存在新建
                new File(newFilePath).mkdirs();
            }

            // 图片名
            String imageName = createName(originalFilename);
            String serverImagePath = newFilePath + imageName;
            // 保存到服务器
            file.transferTo(new File(serverImagePath));

            File chm = new File(serverImagePath);
            chm.setExecutable(true);//设置可执行权限
            chm.setReadable(true);//设置可读权限
            chm.setWritable(true);//设置可写权限

            if (!System.getProperty("os.name").startsWith("Win")) {
                String cmdGrant = "chmod -R 777 " + serverImagePath;
                Runtime.getRuntime().exec(cmdGrant);
            }

            // 生成url地址，返回
            return imageHttpUrl + "/image/" + filePath + imageName;
        } catch (IOException e) {
            LOGGER.info("服务器内部错误：{}", originalFilename);
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 批量上传
     *
     * @param files
     * @return
     * @throws AlertException
     */
    public static List<String> batchUploadFile(List<MultipartFile> files) throws AlertException {
        List<String> urls = new ArrayList<>();
        files.forEach(t -> {
            try {
                urls.add(uploadFile(t));
            } catch (AlertException e) {
                urls.add(t.getOriginalFilename() + " 上传失败!");
            }
        });
        return urls;
    }

    /**
     * 上传图片
     *
     * @param file
     * @return
     */
    public static String uploadFile(MultipartFile file) throws AlertException {
        // 获取当前时间
        String filePath = new SimpleDateFormat("YYYY/MM/dd/").format(new Date());

        String originalFilename = file.getOriginalFilename();

        // 判断文件大小
        if (file.getSize() > fileSize) {
            LOGGER.info("上传图片超过最大限制：" + originalFilename);
            throw new AlertException("上传图片超过最大限制：" + originalFilename);
        }

        try {

            // 完整的保存服务器地址
            String newFilePath = saveFileServerPath + filePath;

            // 判断文件夹是否存在
            if (!new File(newFilePath).exists()) {
                // 不存在新建
                new File(newFilePath).mkdirs();
            }

            // 图片名
            String imageName = createName(originalFilename);
            String serverImagePath = newFilePath + imageName;
            // 保存到服务器
            file.transferTo(new File(serverImagePath));


            File chm = new File(serverImagePath);
            chm.setExecutable(true);//设置可执行权限
            chm.setReadable(true);//设置可读权限
            chm.setWritable(true);//设置可写权限

            if (!System.getProperty("os.name").startsWith("Win")) {
                String cmdGrant = "chmod -R 777 " + serverImagePath;
                Runtime.getRuntime().exec(cmdGrant);
            }

            // 生成url地址，返回
            return fileHttpFile + "/file/" + filePath + imageName;
        } catch (IOException e) {
            LOGGER.info("服务器内部错误：{}", originalFilename);
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 创建文件名
     *
     * @param originalFileName
     * @return
     */
    private static String createName(String originalFileName) {
        // 时间戳
        long tiem = System.currentTimeMillis();
        // 随机字符串
        String uuid = StringUtils.remove(UUID.randomUUID().toString(), "-");

        // 获取文件后缀名
        String fileSuffix = StringUtils.substring(originalFileName, StringUtils.lastIndexOf(originalFileName, "."));

        // 返回文件名
        return tiem + uuid + fileSuffix;
    }


    @Value("${upload.file.size}")
    public void setFileSize(Long fileSize) {
        UploadUtils.fileSize = fileSize;
    }

    @Value("#{'${upload.image.allowuploadtype}'.split(',')}")
    public void setContentTypes(List<String> contentTypes) {
        UploadUtils.contentTypes = contentTypes;
    }

    @Value("${upload.image.size}")
    public void setImageSize(Long imageSize) {
        UploadUtils.imageSize = imageSize;
    }

    @Value("${upload.file.server-path}")
    public void setSaveFileServerPath(String saveFileServerPath) {
        UploadUtils.saveFileServerPath = saveFileServerPath;
    }


    @Value("${upload.image.server-path}")
    public void setSaveImageServerPath(String saveImageServerPath) {
        UploadUtils.saveImageServerPath = saveImageServerPath;
    }

    @Value("${upload.image.http-url}")
    public void setImageHttpUrl(String imageHttpUrl) {
        UploadUtils.imageHttpUrl = imageHttpUrl;
    }

    @Value("${upload.file.http-url}")
    public void setFileHttpFile(String fileHttpFile) {
        UploadUtils.fileHttpFile = fileHttpFile;
    }


    /*
      图片保存预处理逻辑
     */
    public static String advanceSave(String url) {

        if (Faster.isNotNull(url)) {
            return url.replaceAll(imageHttpUrl, "");
        }
        return url;
    }

    /**
     * 图片显示预处理逻辑
     */
    public static String advanceShow(String url) {

        if (Faster.isNotNull(url)) {

            return imageHttpUrl.concat(url);
        }
        return url;
    }
}
